package com.scs.application.modules.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.dto.ExcelImportField;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.modules.base.entity.Dept;
import com.scs.application.modules.base.service.DeptService;
import com.scs.application.modules.base.service.WarehouseService;
import com.scs.application.modules.dept.entity.Apply;
import com.scs.application.modules.dept.entity.Demand;
import com.scs.application.modules.dept.service.ApplyService;
import com.scs.application.modules.dept.service.DemandService;
import com.scs.application.modules.sys.entity.Office;
import com.scs.application.modules.sys.entity.User;
import com.scs.application.modules.sys.enums.OfficeConst;
import com.scs.application.modules.sys.mapper.OfficeMapper;
import com.scs.application.modules.sys.service.OfficeService;
import com.scs.application.modules.sys.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 机构 服务实现类
 * </p>
 */
@Service
@AllArgsConstructor
public class OfficeServiceImpl extends BaseServiceImpl<OfficeMapper, Office> implements OfficeService {

    private UserService userService;

    private DeptService deptService;

    private ApplyService applyService;

    private DemandService demandService;
    private WarehouseService warehouseService;

    @Override
    public Boolean saveOrUpdateOffice(Office entity) {
        if (entity.getId() == null) {
            entity.setSystemCode(getOfficeSystemCode(entity.getParentId()));
        }
        saveOrUpdate(entity);
        //同步科室
        deptService.syncOffice();

        if (OfficeConst.officeType.hospital_dept.equals(entity.getType())) {
            warehouseService.creatByDept(entity.getId());
        }

        return true;
    }

    @Override
    public boolean saveOrUpdate(Office entity) {
        String parentId = entity.getParentId();
        List<Office> childOffices = this.list(Wrappers.<Office>query().eq("parent_id", parentId).eq("inner_code",entity.getInnerCode())
                .eq("name", entity.getName()).ne(StringUtils.isNotBlank(entity.getId()), "id", entity.getId()));
        if (!childOffices.isEmpty()) {
            throw new BusinessException("该机构名称已存在，请勿重复添加！机构名称： %s",childOffices.get(0).getName());
        }
        return super.saveOrUpdate(entity);
    }

    private String getOfficeSystemCode(String parentOfficeId) {
        String systemCode = "";
        String maxChildCode = baseMapper.getMaxOfficeCode(parentOfficeId);
        if (maxChildCode != null) {
            if (StringUtils.isNumeric(maxChildCode)) {
                String parentCode = maxChildCode.substring(0, maxChildCode.length() - 3);
                String subCode = maxChildCode.substring(maxChildCode.length() - 3);
                int sn = Integer.parseInt(subCode) + 1;
                systemCode = parentCode + String.format("%03d", sn);
            } else {
                maxChildCode = null;
            }
        }
        if (maxChildCode == null) {
            Office parentOffice = baseMapper.selectById(parentOfficeId);
            if (parentOffice != null) {
                systemCode = parentOffice.getSystemCode() + "001";
            } else {
                systemCode = "001";
            }
        }
        return systemCode;
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        if (idList.isEmpty()) {
            throw new BusinessException("未选中行");
        }

        // 获取该机构下子机构
        List<Office> officeList = this.list(Wrappers.<Office>query().in(!idList.isEmpty(), "parent_id", idList));

        if (!officeList.isEmpty()) {
            throw new BusinessException("存在子机构，不能删除");
        }

        // 获取该机构的用户
        List<User> userList = userService.list(Wrappers.<User>query().in(!idList.isEmpty(), "office_id", idList));

        if (!userList.isEmpty()){
            throw new BusinessException("机构已拥有用户，不能删除");
        }

        // 获取该机构的科室
        List<Dept> deptList = deptService.list(Wrappers.<Dept>query().in(!idList.isEmpty(), "office_id", idList));

        if (!deptList.isEmpty()){
            List<String> deptIds = deptList.stream().map(o -> o.getId()).collect(Collectors.toList());

            // 科室请领、科室需求产生的业务数据
            List<Apply> applyList = applyService.list(Wrappers.<Apply>query().in(!idList.isEmpty(), "dept_id", deptIds));
            List<Demand> demandList = demandService.list(Wrappers.<Demand>query().in(!idList.isEmpty(), "dept_id", deptIds));

            if (!applyList.isEmpty() || !demandList.isEmpty()){
                throw new BusinessException("机构下科室已存在业务数据，不能删除");
            }
            deptList.forEach( ob -> {
                //删除对应科室
                deptService.removeById(ob.getOfficeId());
            });
            deptService.removeByIds(deptIds);
        }
        //同步科室
        deptService.syncOffice();


        return super.removeCascadeByIds(idList);
    }

    /**@Description： 导入模板字段标题
     */
    @Override
    protected List<ExcelImportField> excelGetFieldHead() {
        List<ExcelImportField> exportHeadList = new ArrayList<ExcelImportField>();
        ExcelImportField headDTO;

        headDTO = new ExcelImportField();
        headDTO.setName("name").setText("机构名称").setCellIndex(0).setRequired(true).setMaxLength(50);
        exportHeadList.add(headDTO);

        headDTO = new ExcelImportField();
        headDTO.setName("innerCode").setText("机构编码").setCellIndex(1).setRequired(true).setMaxLength(30).setUnq(true);
        exportHeadList.add(headDTO);

        headDTO = new ExcelImportField();
        headDTO.setName("parentInnerCode").setText("上级机构编码").setCellIndex(2).setMaxLength(30);
        exportHeadList.add(headDTO);
        return  exportHeadList;
    }


    // 导入数据 到数据库中
    @Override
    protected String excelImportToDb(Map<String, String> reqData, List<Office> itemImportList) {
        List<Office> rootOfficeList = this.list(Wrappers.<Office>query().eq("type", OfficeConst.officeType.hospital));
        if (rootOfficeList.isEmpty()) {
            BusinessException.throwValidFail("未找到机构类型为医院的机构,请先维护");
        }
        if (rootOfficeList.size() > 1) {
            BusinessException.throwValidFail("机构类型为医院的机构不知一个,请检查");
        }
        Office rootOffice = rootOfficeList.get(0);

        Map<String,Office> officeMapByInnerCode = this.list(Wrappers.<Office>query().isNotNull("inner_code"))
                .stream().collect(Collectors.toMap(Office::getInnerCode, item -> item));
        ;

        //新增的机构
        Map<String,Office> officeAddMapByInnerCode = new HashMap<>();
        List<Office> itemImportListAdd = new ArrayList<>();

        String remark = StrUtil.format(
                "用户[{}] {} 导入",
                UserUtils.currentUser().getName(),
                DateUtils.format(DateUtils.nowDate(DateUtils.YYYYMMDDHHMMSS_PATTER2),DateUtils.YYYYMMDDHHMMSS_PATTER2)
        );
        Map<String,Integer> rowNumMap = new HashMap<>();
        AtomicInteger rowNum = new AtomicInteger();
        itemImportList.stream().forEach(item -> {
            rowNum.getAndIncrement();
            if (!officeMapByInnerCode.containsKey(item.getInnerCode())) {
                // 根节点
                if (UtilCommon.strIsNull(item.getParentInnerCode())  ||  StringUtils.equalsAny(item.getParentInnerCode(),"")){
                    item.setParentId(rootOffice.getId());
                }

                item.setSpelling(UtilCommon.getStringPre(PinYinUtils.getPinYin(item.getName()), 20))
                        .setShortname(item.getName())
                        .setType(OfficeConst.officeType.hospital_dept)
                        .setSystemCode(item.getInnerCode())
                ;
                item.setId(IdWorker.getIdStr());
                itemImportListAdd.add(item);
                officeAddMapByInnerCode.put(item.getInnerCode(), item);
                rowNumMap.put(item.getId(),rowNum.get());
            }
        });

        if (itemImportListAdd.isEmpty()) {
            BusinessException.throwValidFail( "没有可新增的机构");
        }

        // 设置父节点
        itemImportListAdd.stream().filter(itemFilter -> StringUtils.isBlank(itemFilter.getParentId())).forEach(item -> {
            if (officeAddMapByInnerCode.containsKey(item.getParentInnerCode())) {
                item.setParentId(officeAddMapByInnerCode.get(item.getParentInnerCode()).getId());
            } else if (officeMapByInnerCode.containsKey(item.getParentInnerCode())) {
                item.setParentId(officeMapByInnerCode.get(item.getParentInnerCode()).getId());
            } else{
                BusinessException.throwValidFail(
                        StrUtil.format(
                                "第[{}]行,机构[{}]未找到上级机构,上级机构编码{}，请检查",
                                rowNumMap.get(item.getId()),
                                item.getName(),
                                item.getParentInnerCode()
                        )
                );
            }
        });

        this.saveOrUpdateBatch(itemImportListAdd);
        return StrUtil.format("新增机构数量:{}",itemImportListAdd.size());
    }
}
